#include "../Poller.h"
#include "../Channel.h"
using namespace yhaida;

Poller::Poller(EventLoop *loop)
    : _mainEventLoop(loop),
      _pollfds(),
      _channels()
{
}
Timestamp Poller::poll(ChannelList *EventLoopActiveChannels, int timeout)
{
    int num = ::poll(&*_pollfds.begin(), _pollfds.size(), timeout);
    Timestamp nowTime(Timestamp::now());

    if (num > 0)
    {
        LOG_TRACE << "events happended";
        fillActiveChannels(num, EventLoopActiveChannels);
    }
    else if (num == 0)
    {
        LOG_TRACE << "nothing happended";
    }
    else
    {
        LOG_SYSERR << "Poller::poll()";
    }
    return nowTime;
}

void Poller::updataChannel(Channel *channel)
{
    assertInLoopThread();
    LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events();
    if (channel->index() < 0) // channel->fd()不在_pollfds中
    {
        //判断是否fd与channel配对,即是否已经注册
        assert(_channels.find(channel->fd()) == _channels.end());
        struct pollfd newpollfd;
        newpollfd.fd = channel->fd();
        newpollfd.events = static_cast<short>(channel->events());
        newpollfd.revents = 0;
        _pollfds.push_back(newpollfd);

        int idx = static_cast<int>(_pollfds.size()) - 1;
        channel->set_index(idx);

        _channels[newpollfd.fd] = channel;
    }
    //更新的不是fd(因为map里面存的是Channel*不用更新啦),是_pollfds里面events
    else
    {
        assert(_channels.find(channel->fd()) != _channels.end());
        assert(_channels[channel->fd()] == channel);
        //通过index去找
        int idx = channel->index();
        assert(0 <= idx && idx < static_cast<int>(_pollfds.size()));
        struct pollfd &pfd = _pollfds[idx];
        //
        assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd() - 1);
        pfd.events = static_cast<short>(channel->events());
        pfd.revents = 0;

        if (channel->isNoneEvent())
        {
            // 代替-1
            // pfd.fd = -1;
            pfd.fd = -channel->fd() - 1;
        }
    }
}

void Poller::fillActiveChannels(int numEvents, ChannelList *EventLoopActiveChannels) const
{
    for (PollerList::const_iterator pfd = _pollfds.begin();
         pfd != _pollfds.end() && numEvents > 0;
         ++pfd)
    {
        if (pfd->revents > 0)
        {
            --numEvents;
            ChannelMap::const_iterator pch = _channels.find(pfd->fd);
            assert(pch != _channels.end());
            Channel *vch = pch->second;
            assert(vch->fd() == pfd->fd);
            vch->setRevents(pfd->revents);
            EventLoopActiveChannels->push_back(vch);
        }
    }
}
//删除PollerList _pollfds中和ChannelMap _channels
void Poller::removeChannel(Channel *channel)
{
    assertInLoopThread();
    LOG_TRACE << "fd = " << channel->fd();
    assert(_channels.find(channel->fd())!=_channels.end());
    assert(_channels[channel->fd()] == channel);
    assert(channel->isNoneEvent());//检验channel->disenableAll()

    int idx = channel->index();

    assert(0<=idx && idx < static_cast<int>(_pollfds.size()));

    const struct pollfd& pfd = _pollfds[idx];
    (void) pfd;
    //检验channel->disenableAll() 里面包含 update(); 
    assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events());
    //1.在Map删除channel
    size_t n = _channels.erase(channel->fd());
    assert(n==1);
    (void) n;
    //2.换到后面然后删除
    if(Utils::implicit_cast<size_t>(idx) == _pollfds.size()-1)
    {
        _pollfds.pop_back();
    }
    else{
        int channelAtEnd = _pollfds.back().fd;
        std::iter_swap(_pollfds.begin()+idx,_pollfds.end()-1);
        if(channelAtEnd<0)//如果被交换的最后一个fd也是isNoneEvent()
        {
            //为了区分fd是否是NoneEvent，不是则-fd-1，后面也可以根据-fd转换为-(-fd-1)-1等于fd来用，如果单纯设置为-1，则不好用了
            channelAtEnd = -channelAtEnd -1;
        }
        //把被交换的fd对应的channel的index更新
        _channels[channelAtEnd]->set_index(idx);
        _pollfds.pop_back();
    }
}